From 5fa0da42006b14017538fedca454ff4c99034ba6 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 26 Jun 2013 10:03:51 +0200 Subject: [PATCH] window: Make process_updates faster Only look at "impl" windows in gdk_window_process_updates_with_mode() since these are the only ones we care about. This avoids a lot of unnecessary calls to g_list_copy() and g_object_ref(). --- gdk/gdkwindow.c | 90 +++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 823e6fe463..31842a7178 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -3615,59 +3615,77 @@ enum { PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN }; +static GList * +find_impl_windows_to_update (GList *list, + GdkWindow *window, + gint recurse_mode) +{ + GList *node; + + if (GDK_WINDOW_DESTROYED (window)) + return list; + + /* Recurse first, so that we process updates in reverse stacking + * order so composition or painting over achieves the desired effect + * for offscreen windows + */ + if (recurse_mode != PROCESS_UPDATES_NO_RECURSE) + { + for (node = window->children; node; node = node->next) + { + GdkWindow *child = node->data; + + if (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN || + (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN && + child->frame_clock == NULL)) + { + list = find_impl_windows_to_update (list, child, recurse_mode); + } + } + } + + /* add reference count so the window cannot be deleted in a callback */ + if (window->impl_window == window) + list = g_list_prepend (list, g_object_ref (window)); + + return list; +} + static void gdk_window_process_updates_with_mode (GdkWindow *window, int recurse_mode) { - GdkWindow *impl_window; + GList *list = NULL; + GList *node; g_return_if_fail (GDK_IS_WINDOW (window)); if (GDK_WINDOW_DESTROYED (window)) return; - /* Make sure the window lives during the expose callouts */ - g_object_ref (window); - - impl_window = gdk_window_get_impl_window (window); - if ((impl_window->update_area) && - !impl_window->update_freeze_count && - !gdk_window_is_toplevel_frozen (window) && + list = find_impl_windows_to_update (list, window, recurse_mode); - /* Don't recurse into process_updates_internal, we'll - * do the update later when idle instead. */ - !impl_window->in_update) - { - gdk_window_process_updates_internal ((GdkWindow *)impl_window); - gdk_window_remove_update_window ((GdkWindow *)impl_window); - } + if (window->impl_window != window) + list = g_list_prepend (list, g_object_ref (window->impl_window)); - if (recurse_mode != PROCESS_UPDATES_NO_RECURSE) + for (node = list; node; node = node->next) { - /* process updates in reverse stacking order so composition or - * painting over achieves the desired effect for offscreen windows - */ - GList *node, *children; + GdkWindow *impl_window = node->data; - children = g_list_copy (window->children); - g_list_foreach (children, (GFunc)g_object_ref, NULL); + if (impl_window->update_area && + !impl_window->update_freeze_count && + !gdk_window_is_toplevel_frozen (impl_window) && - for (node = g_list_last (children); node; node = node->prev) - { - GdkWindow *child = node->data; - if (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN || - (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN && - child->frame_clock == NULL)) - { - gdk_window_process_updates (child, TRUE); - } - g_object_unref (child); - } - - g_list_free (children); + /* Don't recurse into process_updates_internal, we'll + * do the update later when idle instead. */ + !impl_window->in_update) + { + gdk_window_process_updates_internal (impl_window); + gdk_window_remove_update_window (impl_window); + } } - g_object_unref (window); + g_list_free_full (list, g_object_unref); } /** -- 2.30.2